#ifndef __SESSION_H__
#define __SESSION_H__
#include <websocketpp/server.hpp>
#include <websocketpp/config/asio_no_tls.hpp>
#include <unordered_map>
#include <memory>
#include <functional>
#define SESSION_TIMEOUT 30000
#define SESSION_FOREVER -1
typedef enum {UNLOGIN,LOGIN} ss_stat;
class session
{
public:
    session(uint64_t ssid)
    :_ssid(ssid),_stat(UNLOGIN){}
    uint64_t get_ssid()
    {
        return _ssid;
    }
    void set_user(uint64_t uid)
    {
        _uid = uid;
    }
    uint64_t get_user()
    {
        return _uid;
    }
    bool is_login()
    {
        return _stat == LOGIN;
    }
    void set_stat(ss_stat stat)
    {
        _stat = stat;
    }
    void set_timer(wsserver_t::timer_ptr tp)
    {
        _tp = tp;
    }
    wsserver_t::timer_ptr get_timer()
    {
        return _tp;
    }
    ~session(){}
private:
    uint64_t _ssid;
    uint64_t _uid;
    ss_stat _stat;
    wsserver_t::timer_ptr _tp;
};
using session_ptr = shared_ptr<session>;
class session_manager
{
public:
    session_manager(wsserver_t* server)
    :_server(server),_next_ssid(1)
    {
        ILOG("session管理创建成功");
    }
    void append_session(session_ptr ssp)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _sessions.insert(make_pair(ssp->get_ssid(),ssp));
    }
    session_ptr create_session(uint64_t uid,ss_stat stat)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        session_ptr ssp(new session(_next_ssid));
        ssp->set_stat(stat);
        ssp->set_user(uid);
        _sessions.insert(make_pair(_next_ssid,ssp));
        _next_ssid++;
        return ssp;
    }
    session_ptr get_session_by_ssid(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        auto it = _sessions.find(ssid);
        if(it == _sessions.end())
            return session_ptr();
        return it->second;
    }
    void remove_session(uint64_t ssid)
    {
        std::unique_lock<std::mutex> lock(_mutex);
        _sessions.erase(ssid);
    }
    void set_session_time(uint64_t ssid,int ms)
    {
        session_ptr ssp = get_session_by_ssid(ssid);
        if(ssp.get()==nullptr)
            return;
        wsserver_t::timer_ptr tp = ssp->get_timer();
        //永久情况设置永久
        if(tp.get()==nullptr && ms == SESSION_FOREVER)
            return;
        //永久情况设置定时删除
        else if(tp.get()==nullptr && ms != SESSION_FOREVER)
        {
            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms
                ,std::bind(&session_manager::remove_session,this,ssid));
            ssp->set_timer(tmp_tp);
        }
        //定时删除情况设置永久
        else if(tp.get()!=nullptr && ms == SESSION_FOREVER)
        {
            tp->cancel();
            _server->set_timer(0,std::bind(&session_manager::append_session,this,ssp));
            ssp->set_timer(wsserver_t::timer_ptr());
        }
        //定时删除情况重置时间
        else if(tp.get()!=nullptr && ms != SESSION_FOREVER)
        {
            tp->cancel();
            _server->set_timer(0,std::bind(&session_manager::append_session,this,ssp));
            wsserver_t::timer_ptr tmp_tp = _server->set_timer(ms
                ,std::bind(&session_manager::remove_session,this,ssid));
            ssp->set_timer(tmp_tp);
        }
    }
    ~session_manager()
    {}
private:
    uint64_t _next_ssid;
    std::mutex _mutex;
    std::unordered_map<uint64_t,session_ptr> _sessions;
    wsserver_t* _server;
};
#endif
